home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 43
/
Amiga Format CD43 (1999)(Future Publishing)(GB)(Track 1 of 2)[!][issue 1999-09].iso
/
-serious-
/
archivers
/
xpk
/
xpk_source
/
prefs
/
xpkmasterprefs.c
< prev
Wrap
C/C++ Source or Header
|
1999-06-14
|
17KB
|
644 lines
#define NAME "XpkMasterPrefs"
#define DISTRIBUTION "(Freeware) "
#define REVISION "18"
//#define DEBUG
/* Programmheader
Name: XpkMasterPrefs
Author: SDI
Distribution: Freeware
Description: xpk prefs loader, like IPrefs
Compileropts: -
Linkeropts: -gsi (no startup)
1.0 25.12.96 : first Version
1.1 26.12.96 : nearly redefined xpkprefs structures - a lot of changes
1.2 27.12.96 : some fixes
1.3 30.12.96 : did a bit on Recog function
1.4 02.01.97 : added correctness check of BufPattern
1.5 11.01.97 : corrected some errors
1.6 28.02.97 : changed some semaphore specific stuff
1.7 01.03.97 : added Version info to MainPrefs
1.8 07.03.97 : fixed RecogFunc
1.9 24.03.97 : added DEBUG stuff
1.10 28.03.97 : added last function and ReadArgs
1.11 02.04.97 : XpkTypeData changed, ListData now internal structure
1.12 03.04.97 : added DEBUG info, debuged RecogFunction
1.13 04.04.97 : buffer now 2 K
1.14 06.06.97 : name pattern no case independant
1.15 17.06.97 : fixed error, when no name and no filepattern
1.16 18.06.97 : added filelength check and OR parameter
1.17 13.08.97 : fixed Enforcer hit
1.18 16.01.98 : fixed possible design flaw
*/
/*
How to parse the type list:
- The struct XpkTypeData of the first matching structure is returned.
- If no type matches, the default is returned.
- Scan goes always in linear order from the beginning to end. (and never
reverse).
- if no file name is given, the xtp_FilePattern field is ignored.
*/
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/iffparse.h>
#include <utility/tagitem.h>
#include <prefs/prefhdr.h>
#include <xpk/xpkprefs.h>
#include <exec/memory.h>
#include "SDI_defines.h"
#define SDI_TO_ANSI
#include "SDI_ASM_STD_protos.h"
/**************************************************************************
*
* Standard prefs specific data structure. xps_PrefsData points to this.
*
* xssd_TypeList nodes are of type XpkTypeNode.
*
*
*/
struct XpkStdSemaphoreData {
struct List xssd_TypeList; /* list of file types */
ULONG xssd_Buffer1Size; /* size of following buffer */
STRPTR xssd_Buffer1; /* pointer to buffer */
};
struct XpkTypeNode {
struct Node xtn_Node; /* standard node structure */
ULONG xtn_Size; /* hold complete size to free */
struct XpkTypePrefs xtn_TypePrefs; /* real data */
};
#define RECOGBUFSIZE 2048
#define PARAM "QUIT/S"
#ifdef __MAXON__
#define __asm
struct Library *IFFParseBase;
#else
#define iffparsebase IFFParseBase
#endif
struct DosLibrary *DOSBase;
struct ExecBase *SysBase;
void CorrectAdr(APTR pos, APTR mempos);
void DoPrefsCreation(struct XpkPrefsSemaphore *sem);
void ClearTypeList(struct XpkStdSemaphoreData *sem);
void ClearMainPrefs(struct XpkPrefsSemaphore *sem);
struct XpkTypeData * __asm RecogFunc(register __a0 STRPTR buf,
register __a1 STRPTR name, register __d0 ULONG bufsize,
register __d1 ULONG fullsize, register __a2 struct TagItem *);
UBYTE CheckHex(STRPTR *data, LONG number);
ULONG CheckBufPattern(STRPTR pattern);
UBYTE GetCharacter(STRPTR pattern);
/* these two return zero, when name matches or defined values, when not */
ULONG CheckPattern(STRPTR pattern, STRPTR buffer, ULONG size, ULONG fsize);
ULONG MatchBufPattern(STRPTR pattern, STRPTR buffer, ULONG size, ULONG fsize);
ULONG MatchFileName(STRPTR pattern, STRPTR name);
#define MATCHERR_PATTERN_INCORRECT 1
#define MATCHERR_NO_MEMORY 2
#define MATCHERR_BUFFER_TO_SHORT 3
#define MATCHERR_NO_MATCH 4
#define MATCHERR_NO_SIZE_MATCH 5
ULONG start(void) /* not named main, to get error with startup code ! */
{
struct DosLibrary *dosbase;
struct XpkPrefsSemaphore *semaphore;
struct Process *task;
struct Message *msg = 0;
struct RDArgs *rda;
LONG quit = 0;
SysBase = (*((struct ExecBase **) 4));
if(!(task = (struct Process *) FindTask(0))->pr_CLI)
{
WaitPort(&task->pr_MsgPort);
msg = GetMsg(&task->pr_MsgPort);
/* no tooltype check now, so means always start semaphore */
}
else
{
if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
{
DOSBase = dosbase;
if((rda = ReadArgs(PARAM, &quit, 0)))
FreeArgs(rda);
CloseLibrary((struct Library *) dosbase);
}
/* does not recognize failed ReadArgs - normal start in this case */
}
Forbid();
semaphore = (struct XpkPrefsSemaphore *) FindSemaphore(XPKPREFSSEMNAME);
if(quit)
{
if(semaphore)
{
ObtainSemaphoreShared((struct SignalSemaphore *) semaphore);
Signal(semaphore->xps_MasterTask, SIGBREAKF_CTRL_C);
ReleaseSemaphore((struct SignalSemaphore *) semaphore);
}
Permit();
}
else if(!semaphore && (dosbase = (struct DosLibrary *)
OpenLibrary("dos.library", 37)))
{
DOSBase = dosbase;
if((semaphore = (struct XpkPrefsSemaphore *) AllocMem(sizeof(struct
XpkPrefsSemaphore) + sizeof(struct XpkStdSemaphoreData), MEMF_PUBLIC|MEMF_CLEAR)))
{
struct NotifyRequest *notifyrequest;
struct XpkStdSemaphoreData *sd = (struct XpkStdSemaphoreData *)
(((STRPTR) semaphore) + sizeof(struct XpkPrefsSemaphore));
/* both structures are allocated with one AllocMem */
InitSemaphore((struct SignalSemaphore *) semaphore);
semaphore->xps_Semaphore.ss_Link.ln_Type = NT_SEMAPHORE;
semaphore->xps_Semaphore.ss_Link.ln_Name = XPKPREFSSEMNAME;
semaphore->xps_PrefsData = sd;
// semaphore->xps_Version = 0;
semaphore->xps_PrefsType = XPREFSTYPE_STANDARD;
// semaphore->xps_ProgressFunc = 0;
semaphore->xps_RecogSize = RECOGBUFSIZE;
semaphore->xps_RecogFunc = (struct XpkTypeData *(*)()) RecogFunc;
semaphore->xps_MasterTask = (struct Task *) task;
sd->xssd_TypeList.lh_Type = NT_USER;
sd->xssd_TypeList.lh_Head = (struct Node *) &sd->xssd_TypeList.lh_Tail;
sd->xssd_TypeList.lh_TailPred = (struct Node *) &sd->xssd_TypeList.lh_Head;
AddSemaphore((struct SignalSemaphore *) semaphore);
Permit();
if((notifyrequest = (struct NotifyRequest *)
AllocMem(sizeof(struct NotifyRequest), MEMF_CLEAR)))
{
ULONG signr;
if((signr = AllocSignal(-1L)) != -1)
{
notifyrequest->nr_Name = "ENV:xpkmaster.prefs";
notifyrequest->nr_Flags = NRF_SEND_SIGNAL | NRF_NOTIFY_INITIAL;
notifyrequest->nr_stuff.nr_Signal.nr_Task = FindTask(0);
notifyrequest->nr_stuff.nr_Signal.nr_SignalNum = signr;
if((StartNotify(notifyrequest)) == DOSTRUE)
{
ULONG signal = 0;
while(!(signal & SIGBREAKF_CTRL_C))
if((signal = Wait(1 << signr | SIGBREAKF_CTRL_C)) & (1 << signr))
DoPrefsCreation(semaphore);
EndNotify(notifyrequest);
}
FreeSignal(signr);
}
FreeMem(notifyrequest, sizeof(struct NotifyRequest));
}
ObtainSemaphore((struct SignalSemaphore *) semaphore);
RemSemaphore((struct SignalSemaphore *) semaphore);
ClearTypeList((struct XpkStdSemaphoreData *) semaphore->xps_PrefsData);
ClearMainPrefs(semaphore);
FreeMem(semaphore, sizeof(struct XpkPrefsSemaphore) +
sizeof(struct XpkStdSemaphoreData));
}
else
Permit();
CloseLibrary((struct Library *) dosbase);
}
else
Permit();
if(msg)
{
Forbid();
ReplyMsg(msg);
}
return 0;
}
/* changes relative addresses into normal ones */
void CorrectAdr(APTR pos, APTR mempos)
{
if(*(ULONG *)pos)
*(ULONG *)pos += (ULONG) mempos;
}
void ClearTypeList(struct XpkStdSemaphoreData *sd)
{
struct Node *n;
while((n = RemHead(&sd->xssd_TypeList)))
FreeMem(n, ((struct XpkTypeNode *) n)->xtn_Size);
}
void ClearMainPrefs(struct XpkPrefsSemaphore *sem)
{
struct XpkStdSemaphoreData *sd = (struct XpkStdSemaphoreData *) sem->xps_PrefsData;
if(sd->xssd_Buffer1)
FreeMem(sd->xssd_Buffer1, sd->xssd_Buffer1Size);
sem->xps_MainPrefs = 0;
sd->xssd_Buffer1Size = 0;
sd->xssd_Buffer1 = 0;
}
void DoPrefsCreation(struct XpkPrefsSemaphore *sem)
{
struct Library *iffparsebase;
struct ContextNode *cn;
struct IFFHandle *iff;
ULONG prefsversion = 0;
ObtainSemaphore(&sem->xps_Semaphore);
ClearTypeList((struct XpkStdSemaphoreData *) sem->xps_PrefsData);
ClearMainPrefs(sem);
if(!(iffparsebase = OpenLibrary("iffparse.library", 37)))
return;
#ifdef __MAXON__
IFFParseBase = iffparsebase;
#endif
if((iff = AllocIFF()))
{
if((iff->iff_Stream = Open("ENV:xpkmaster.prefs", MODE_OLDFILE)))
{
InitIFFasDOS(iff);
if(!OpenIFF(iff, IFFF_READ))
{
LONG a[] = { ID_PREF, ID_PRHD, ID_PREF, ID_XPKT, ID_PREF, ID_XPKM};
if(!StopChunks(iff, a, 3))
{
ULONG error = 0;
while(!error)
{
if(ParseIFF(iff,IFFPARSE_SCAN))
break;
cn = CurrentChunk(iff);
switch(cn->cn_ID)
{
case ID_PRHD:
{
struct PrefHeader prh;
ReadChunkBytes(iff, &prh, sizeof(struct PrefHeader));
prefsversion = prh.ph_Version;
/* use this, when internal version is greater than one. In this
case the value is version of XPKT chunks */
} break;
case ID_XPKT:
{
struct XpkTypeNode *buf;
ULONG size;
size = cn->cn_Size + sizeof(struct Node) + sizeof(ULONG);
if((buf = (struct XpkTypeNode *) AllocMem(size, MEMF_PUBLIC|MEMF_CLEAR)))
{
struct XpkTypePrefs *pref = &buf->xtn_TypePrefs;
ReadChunkBytes(iff, pref, cn->cn_Size);
CorrectAdr(&pref->xtp_NamePattern, pref);
CorrectAdr(&pref->xtp_FilePattern, pref);
CorrectAdr(&pref->xtp_TypeName, pref);
CorrectAdr(&pref->xtp_PackerData, pref);
buf->xtn_Node.ln_Name = pref->xtp_TypeName;
buf->xtn_Node.ln_Type = NT_USER;
buf->xtn_Size = size;
pref->xtp_PackerData->xtd_Memory = 0;
pref->xtp_PackerData->xtd_MemorySize = 0;
AddTail(&((struct XpkStdSemaphoreData *)sem->xps_PrefsData)->xssd_TypeList, (struct Node *) buf);
}
else error = 1;
} break;
case ID_XPKM:
{
struct XpkMainPrefs *pref;
struct XpkStdSemaphoreData *sd =
(struct XpkStdSemaphoreData *) sem->xps_PrefsData;
struct XpkTypeData *p;
ClearMainPrefs(sem);
if((pref = (struct XpkMainPrefs *) AllocMem(cn->cn_Size, MEMF_PUBLIC|MEMF_CLEAR)))
{
ReadChunkBytes(iff, pref, cn->cn_Size);
CorrectAdr(&pref->xmp_DefaultType, pref);
p = pref->xmp_DefaultType;
/* XpkTypeData newer than version 0 may be incorrect, so set to 0 */
p->xtd_Version = 0;
p->xtd_Memory = 0;
p->xtd_MemorySize = 0;
sem->xps_MainPrefs = pref;
sd->xssd_Buffer1Size = cn->cn_Size;
sd->xssd_Buffer1 = (STRPTR) pref;
}
else error = 1;
} break;
}
}
}
CloseIFF(iff);
}
Close(iff->iff_Stream);
}
FreeIFF(iff);
}
CloseLibrary(IFFParseBase);
ReleaseSemaphore(&sem->xps_Semaphore);
}
UBYTE CheckHex(STRPTR *data, LONG number)
{
LONG num;
do
{
num = number;
while(num-- && isxdigit(*((*data)++)))
;
if(++num)
return MATCHERR_PATTERN_INCORRECT;
} while(isxdigit(**data));
return 0;
}
/* return 0, when pattern is valid */
ULONG CheckBufPattern(STRPTR pattern)
{
while(*pattern)
{
ULONG a;
STRPTR s;
s = pattern;
switch(*(pattern++))
{
case 'l': a = 1; break;
case 'h': a = 1; break;
case 'm': a = 1; break;
case 'v': a = 2; break;
case 'r': a = 4; break;
case 'g': a = 4; break;
case 's': a = 2; break;
case '|': a = 0; break;
default: return MATCHERR_PATTERN_INCORRECT; break;
}
if(a && CheckHex(&pattern, a))
return MATCHERR_PATTERN_INCORRECT;
if((*s == 'm' && (pattern-s) > 5) ||
((*s == 'l' || *s == 'h') && (pattern-s) > 9))
return MATCHERR_PATTERN_INCORRECT;
/* only word data for 'm' and longword for 'l' and 'h' + 1 '.' */
}
return 0;
}
UBYTE GetCharacter(STRPTR pattern)
{
UBYTE i = 0, c;
ULONG size = 2;
while(size--)
{
i <<= 4;
if((c = toupper(*(pattern++))) >= 'A')
i += c + 10 - 'A';
else
i += c - '0';
}
return i;
}
ULONG CheckPattern(STRPTR pattern, STRPTR buffer, ULONG size, ULONG fsize)
{
STRPTR bufpos = buffer;
ULONG i;
UBYTE j, k;
STRPTR errpos, str;
while(pattern && *pattern && *pattern != '|')
{
switch(*(pattern++))
{
case 'm':
i = strtoul(pattern, &errpos, 16);
pattern = errpos; /* first non hex char is next command */
if(i >= size)
return MATCHERR_BUFFER_TO_SHORT;
else
bufpos = buffer + i;
break;
case 'l':
i = strtoul(pattern, &errpos, 16);
pattern = errpos; /* first non hex char is next command */
if(fsize > i)
return MATCHERR_NO_SIZE_MATCH;
break;
case 'h':
i = strtoul(pattern, &errpos, 16);
pattern = errpos; /* first non hex char is next command */
if(fsize < i)
return MATCHERR_NO_SIZE_MATCH;
break;
case 'v':
while(isxdigit(*pattern))
{
j = GetCharacter(pattern); pattern += 2;
if(bufpos >= buffer + size)
return MATCHERR_BUFFER_TO_SHORT;
if(j != *(bufpos++))
return MATCHERR_NO_MATCH;
}
break;
case 'r':
while(isxdigit(*pattern))
{
errpos = buffer;
k = GetCharacter(pattern); pattern += 2;
j = GetCharacter(pattern); pattern += 2;
while(errpos < buffer + size)
{
if(*errpos >= k && *errpos <= j)
return MATCHERR_NO_MATCH;
++errpos;
}
}
break;
case 'g':
while(isxdigit(*pattern))
{
k = GetCharacter(pattern); pattern += 2;
j = GetCharacter(pattern); pattern += 2;
if(bufpos >= buffer + size)
return MATCHERR_BUFFER_TO_SHORT;
if(*bufpos < k && *bufpos > j)
return MATCHERR_NO_MATCH;
++bufpos;
}
break;
case 's':
bufpos = buffer;
while(isxdigit(*pattern))
{
str = pattern;
j = GetCharacter(str); str += 2;
while(bufpos < buffer + size && *bufpos != j)
++bufpos;
if(*bufpos == j)
{
errpos = ++bufpos;
while(isxdigit(*str) && bufpos < buffer + size &&
GetCharacter(str) == *bufpos)
{
str += 2; ++bufpos;
}
if(!isxdigit(*str))
pattern = str; /* exits while loop */
else
bufpos = errpos; /* reset buffer */
}
else
return MATCHERR_NO_MATCH;
}
break;
default: return MATCHERR_NO_MATCH; break;
}
}
return 0;
}
ULONG MatchBufPattern(STRPTR pattern, STRPTR buffer, ULONG size, ULONG fsize)
{
ULONG err = MATCHERR_NO_MATCH;
if(!pattern || CheckBufPattern(pattern))
{
#ifdef DEBUG
Printf("MatchBufPattern: CheckBufPattern(%s) failed\n", pattern);
#endif
return MATCHERR_PATTERN_INCORRECT;
}
while(*pattern)
{
if(!(err = CheckPattern(pattern, buffer, size, fsize)))
return 0;
else /* search for next OR field or end of pattern */
{
while(*pattern && *pattern != '|')
++pattern;
if(*pattern == '|')
++pattern;
}
}
return err;
}
ULONG MatchFileName(STRPTR pattern, STRPTR name)
{
ULONG a, b = MATCHERR_NO_MATCH;
STRPTR buf;
if(!pattern)
return MATCHERR_PATTERN_INCORRECT;
a = (strlen(pattern)<<1) + 10; /* pattern match buffer */
if(!(buf = (STRPTR) AllocMem(a, MEMF_ANY)))
return MATCHERR_NO_MEMORY;
if(ParsePatternNoCase(pattern, buf, a) >= 0 && MatchPatternNoCase(buf, name))
b = 0;
FreeMem(buf, a);
return b;
}
struct XpkTypeData * __asm RecogFunc(register __a0 STRPTR buf,
register __a1 STRPTR name, register __d0 ULONG bufsize,
register __d1 ULONG fullsize, register __a2 struct TagItem *tags)
{
struct XpkPrefsSemaphore *sem;
struct XpkTypePrefs *xp;
struct Node *n;
#ifdef DEBUG
if(tags)
{
while(tags->ti_Tag)
VPrintf("%ld %ld\n", tags++);
}
#endif
if(!buf || !bufsize)
return 0;
sem = (struct XpkPrefsSemaphore *) FindSemaphore(XPKPREFSSEMNAME);
/* I can do without ObtainSemaphore, because when I'm called here the
semaphore is owned already and surely exists */
if(sem->xps_PrefsData)
{
for(n = ((struct XpkStdSemaphoreData *)sem->xps_PrefsData)->
xssd_TypeList.lh_Head; n->ln_Succ; n = n->ln_Succ)
{
xp = &((struct XpkTypeNode *) n)->xtn_TypePrefs;
if((name && xp->xtp_Flags & XPKT_NamePattern) ||
xp->xtp_Flags & XPKT_FilePattern)
{
if(!(xp->xtp_Flags & XPKT_FilePattern) || !MatchBufPattern(
xp->xtp_FilePattern, buf, bufsize, fullsize))
{
if(!name || !(xp->xtp_Flags & XPKT_NamePattern) || !MatchFileName(
xp->xtp_NamePattern, name))
{
#ifdef DEBUG
Printf("RecogFunc: matched '%s'\n", xp->xtp_TypeName);
#endif
return xp->xtp_PackerData;
}
#ifdef DEBUG
else
Printf("RecogFunc: no namematch '%s'\n", xp->xtp_TypeName);
#endif
}
#ifdef DEBUG
else
Printf("RecogFunc: no bufmatch '%s'\n", xp->xtp_TypeName);
#endif
}
#ifdef DEBUG
else
Printf("RecogFunc: no patterns '%s'\n", xp->xtp_TypeName);
#endif
}
}
if(sem->xps_MainPrefs)
return sem->xps_MainPrefs->xmp_DefaultType;
return 0;
}